//	COPYRIGHT (C) 1981 BY BOARD OF TRUSTEES,
//	LELAND STANFORD JUNIOR UNIVERSITY

//	COPYRIGHT (C) 1981 BY BOARD OF TRUSTEES,
//	LELAND STANFORD JUNIOR UNIVERSITY

//APRIL 25, 1978.
//BCPL-CONGEN WRITTEN BY RAY CARHART.  THIS FILE CONTAINS ASSORTED
//SET-MANIPULATION FUNCTIONS.  SETS ARE BIT PATTERNS
//CONTAINED IN VECTORS.  THERE ARE R2WDSZ BITS STORED IN EACH
//VECTOR LOCATION AND NSETWDSM1 IS ONE LESS THAN THE NUMBER OF
//WORDS NEEDED TO REPRESENT THE SET (IE, NSETWDSM1 IS COMPUTED BY
//(HIGHEST SET ELEMENT)>>P2WDSZ).  IT IS THE CALLERS RESPONSIBILITY
//TO SET NSETWDSM1, AND TO RESTORE IT TO ITS OLD VALUE WHEN DONE WITH
//THE SET FUNCTIONS.
STATIC $( NSETWDSM1 = NIL $);

LET SETSIZE(SET) = VALOF
 $( STATIC $( FOURBITSZ = TABLE 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4;
              PARTSET = NIL; COUNT = NIL $);
 COUNT:=0;
 FOR SETI=SET TO SET+NSETWDSM1 DO
  $(
  PARTSET:=!SETI;
  UNTIL PARTSET=0 DO
   $(
   COUNT+:=FOURBITSZ![PARTSET BITAND #17];
   PARTSET:=PARTSET>>4
   $)
  $);
 RESULTIS COUNT
 $);

LET NTHELEM(N,SET) = VALOF
 TEST SETSIZE(SET)<N THEN RESULTIS PLUSINF
 OR
  $( STATIC $( ELEM = NIL; PARTSET = NIL; NEL = NIL;
               ETOP = 1<<[R2WDSZ-1] $);
  IF N=0 DO RESULTIS -1;
  ELEM:=1;
  PARTSET:=!SET;
  NEL:=0;
  $(
  IF [PARTSET BITAND ELEM] NE 0 DO TEST N>1 THEN N-:=1 OR RESULTIS NEL;
  NEL+:=1;
  TEST ELEM=ETOP THEN $( SET+:=1; PARTSET:=!SET; ELEM:=1 $)
  OR ELEM:=ELEM<<1;
  $) REPEAT
  $);

//LET NTHELEM(N,SET) = VALOF $( STATIC $( ANS = NIL $);
//OUTS("NTHELEM(");OUTNO(N);OUTS(",");OUTOCT(!SET); OUTS(") GIVES ");
//ANS:=NTHELEM0(N,SET); OUTNOL(ANS);
//RESULTIS ANS $);
LET LOWELEM(SET) = VALOF
 $( STATIC $( RIGHTBIT = TABLE 0,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0;
              ELEM = NIL; PARTSET = NIL $);
 ELEM:=0;
 FOR SETI=SET TO SET+NSETWDSM1 DO
  TEST !SETI=0 THEN ELEM+:=R2WDSZ
  OR
   $(
   PARTSET:=!SETI;
   $(
   TEST [PARTSET BITAND #17]=0 THEN ELEM+:=4
   OR RESULTIS ELEM+RIGHTBIT![PARTSET BITAND #17];
   PARTSET:=PARTSET>>4
   $) REPEAT
   $);
 RESULTIS -1
 $);

LET MAKESET() = NEWVEC(NSETWDSM1);

LET FREESET(SET) BE FREEVEC(SET);

LET SETEQUAL(SETA,SETB) = VALOF
 $(
 FOR I=0 TO NSETWDSM1 DO UNLESS SETA!I=SETB!I DO RESULTIS FALSE;
 RESULTIS TRUE
 $);

LET FLIPELEM(ELEM,SET) = VALOF
 $(
 SET![ELEM>>P2WDSZ]NEQV:=1<<[ELEM NEQV [[ELEM>>P2WDSZ]<<P2WDSZ]];
 RESULTIS SET
 $);

LET TESTELEM(ELEM,SET) =
 0 NE [SET![ELEM>>P2WDSZ] BITAND
   [1<<[ELEM NEQV [[ELEM>>P2WDSZ]<<P2WDSZ]]]];

LET PUTELEM(ELEM,SET) =
 (TESTELEM(ELEM,SET) -> SET,FLIPELEM(ELEM,SET));

LET REMELEM(ELEM,SET) =
 (TESTELEM(ELEM,SET) -> FLIPELEM(ELEM,SET),SET);

LET DUNION(SETA,SETB) = VALOF
 $(
 FOR I=0 TO NSETWDSM1 DO SETA!I BITOR:=SETB!I;
 RESULTIS SETA
 $);

LET DUNDISJ(SETA,SETB) = VALOF
 $(
 FOR I=0 TO NSETWDSM1 DO SETA!I NEQV :=SETB!I;
 RESULTIS SETA
 $);

LET DINTERSECT(SETA,SETB) = VALOF
 $(
 FOR I=0 TO NSETWDSM1 DO SETA!I BITAND :=SETB!I;
 RESULTIS SETA
 $);

LET UNION(USET,SETA,SETB) = VALOF
 $(
 FOR I=0 TO NSETWDSM1 DO USET!I:=SETA!I BITOR SETB!I;
 RESULTIS USET
 $);

LET UNIONDISJ(USET,SETA,SETB) = VALOF
 $(
 FOR I=0 TO NSETWDSM1 DO USET!I:=SETA!I NEQV SETB!I;
 RESULTIS USET
 $);

LET INTERSECT(ISET,SETA,SETB) = VALOF
 $(
 FOR I=0 TO NSETWDSM1 DO ISET!I:=SETA!I BITAND SETB!I;
 RESULTIS ISET
 $);

LET COPYSET(CSET,SET) = VALOF
 $(
 FOR I=0 TO NSETWDSM1 DO CSET!I:=SET!I;
 RESULTIS CSET
 $);

LET ZEROSET(SET) =VALOF
 $(
 FOR SETI=SET TO SET+NSETWDSM1 DO !SETI:=0;
 RESULTIS SET
 $);

